-
Notifications
You must be signed in to change notification settings - Fork 2.3k
feat: add paginated list decorators for prompts, resources, and tools #1286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a some docs with examples? not sure if we have good docs for the lowlevel api but some usage examples would be great (if not just to help with reviewing).
Otherwise this looks good to me. happy with the separate functions to avoid breaking changes. keen to know how you think we should approach this in the high level interface.
91fa584
to
9d72703
Compare
Updated the docs, added example code, and included testing in the PR desription |
66ee42f
to
83d4890
Compare
83d4890
to
550e3fe
Compare
Add list_prompts_paginated, list_resources_paginated, and list_tools_paginated decorators to support cursor-based pagination for listing endpoints. These decorators: - Accept a cursor parameter (can be None for first page) - Return the respective ListResult type directly - Maintain backward compatibility with existing non-paginated decorators - Update tool cache for list_tools_paginated Also includes simplified unit tests that verify cursor passthrough. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Apply automatic formatting from ruff to ensure code meets project standards: - Remove trailing whitespace - Adjust line breaks for consistency - Format function arguments according to line length limits
550e3fe
to
70435e5
Compare
- Create mcp_simple_pagination example server demonstrating all three paginated endpoints - Add pagination snippets for both server and client implementations - Update README to use snippet-source pattern for pagination examples - Move mutually exclusive note to blockquote format for better visibility - Complete example shows tools, resources, and prompts pagination with different page sizes
70435e5
to
5d823c8
Compare
.pre-commit-config.yaml
Outdated
@@ -25,22 +25,22 @@ repos: | |||
hooks: | |||
- id: ruff-format | |||
name: Ruff Format | |||
entry: uv run ruff | |||
entry: uv run --frozen ruff |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for below
entry: uv run --frozen ruff | |
entry: ruff |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea, updated
def list_prompts_paginated(self): | ||
def decorator(func: Callable[[types.Cursor | None], Awaitable[types.ListPromptsResult]]): | ||
logger.debug("Registering handler for PromptListRequest with pagination") | ||
|
||
async def handler(req: types.ListPromptsRequest): | ||
result = await func(req.params.cursor if req.params else None) | ||
return types.ServerResult(result) | ||
|
||
self.request_handlers[types.ListPromptsRequest] = handler | ||
return func | ||
|
||
return decorator | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't the list_prompts
handle pagination?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well there were a few paths and I wanted to just put something down to start the discussion.
There were three options I was thinking:
- Separate decorators (current state of this PR):
- Backwards compatible, it won't break existing uses of list_prompts where it's used on a function that takes no arguments
- Makes implementation of this easier, rather than having to do inspection on the
func
being passed in to see whether it takes an argument or not, it's just separated into two methods
- Single decorator but break backwards compatibility:
- This would just be changing list_prompts to look exactly like list_prompts_paginated, all
func
s passed in need to take in an argument oftypes.Cursor | None
- Breaks potentially a lot of existing uses of the lowlevel code
- This would just be changing list_prompts to look exactly like list_prompts_paginated, all
- Single decorator, union type:
- This would be having a single
list_prompts
that takes in afunc
that looks likeCallable[[types.Cursor | None], Awaitable[types.ListPromptsResult]] | Callable[[], Awaitable[list[types.Prompt]]]
- Makes it backwards compatible while allowing for an optional cursor
- Makes implementation a bit trickier by having to do inspection on the function to make sure it fits the shapes expected.
- This would be having a single
Were you preferring option 2 or 3?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm probably leaning towards option 3 now though :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backward compatibility: Modifying the existing decorators to require a cursor parameter in the callback would break existing uses of these decorators.
You can make it optional, can't you?
Summary
This PR adds paginated decorator methods for listing prompts, resources, and tools to support cursor-based pagination as defined in the MCP spec.
Design Decision for Discussion
I chose to implement these as new decorator methods (
list_prompts_paginated
,list_resources_paginated
,list_tools_paginated
) rather than modifying the existing decorators.Rationale:
Alternative considered:
Looking for feedback on whether this approach makes sense or if there's a preferred pattern for handling this migration.
Changes
list_prompts_paginated()
decorator that accepts a cursor parameterlist_resources_paginated()
decorator that accepts a cursor parameterlist_tools_paginated()
decorator that accepts a cursor parameterlist_tools_paginated
Test plan
🤖 Generated with Claude Code
👨 Below generated by the human, Max Isbey
Manual testing
I spun up the MCP inspector and ran the example pagination server in both stdio mode and SSE mode. Below is some testing evidence using the SSE mode:
Clicking "List More Resources" correctly lists all 30 resources:
Note: this works for prompts and tools as well
Requesting a resource works:
Running the pagination client example code works listing all 30 resources: